package com.wh1200.mybatis.xmlless.resolver

import com.wh1200.mybatis.xmlless.config.BaseResolverTest
import com.wh1200.xmlless.test.model.JoinObjectEntity
import com.wh1200.xmlless.test.model.JoinEntityDAO
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import kotlin.reflect.jvm.javaMethod
import kotlin.test.assertContains
import kotlin.test.assertEquals
import kotlin.test.assertNotNull

/**
 *
 * @author 吴昊
 * @date 2024/1/25 11:05
 * @since v0.0.0
 * @version 1.0
 */

class JoinEntityDAOResolver : BaseResolverTest(
    JoinEntityDAO::class.java
) {

  @Test
  @DisplayName("测试查询条件包含大于2级关联的对象的属性")
  fun resolve2() {
    val method = JoinEntityDAO::findByGrandParent2.javaMethod!!
    val q = createQueryForMethod(method)
    q.exception?.printStackTrace()
    val sql = q.sql
    assertNotNull(sql)
    val tables = q.query?.containedTables()
    assertNotNull(tables)
    assertContains(tables, "p")
    assertContains(tables, "p_p")
    val from = q.query?.resolveFrom()
    assertNotNull(from)
    assert(from.joins.size > 2)
  }

  @Test
  @DisplayName("测试查询条件包含大于2级关联的对象的属性")
  fun resolve3() {
    val method = JoinEntityDAO::findByGrandParent3.javaMethod!!
    val q = createQueryForMethod(method)
    q.exception?.printStackTrace()
    val sql = q.sql
    assertNotNull(sql)
  }

  @Test
  @DisplayName("主键字段名称不是id，使用findById也应该正确匹配主键")
  fun resolveKeyFieldName() {
    val method = JoinEntityDAO::findById.javaMethod!!
    val q = createQueryForMethod(method)
    q.exception?.printStackTrace()
    val sql = q.sql
    assertNotNull(sql)
    assertContains(sql, "id1 = #{id}")
  }

  @Test
  @DisplayName("逻辑删除自动记录删除人id和删除时间")
  fun deleteById() {
    val method = JoinEntityDAO::deleteById.javaMethod!!
    val q = createQueryForMethod(method)
    q.exception?.printStackTrace()
    val sql = q.sql
    assertNotNull(sql)
    assertContains(sql, "id1 = #{id}")
    assertContains(sql, "deleted_by = __CURRENT_USER_ID__,")
    assertContains(sql, "deleted_date = CURRENT_TIMESTAMP,")
  }

  @Test
  @DisplayName("测试查询条件包含大于2级关联的对象的属性")
  fun resolve() {
    val method = JoinEntityDAO::findByGrandParent.javaMethod!!
    val methodInfo = createMethodInfo(method)
    val q = createQueryForMethod(method)
    q.exception?.printStackTrace()
    val sql = q.sql
    assertNotNull(sql)
    assertContains(sql, "parentObj.id2 = join_object_entity.parent_id")
    assertContains(
        sql,
        "parentObj_parent_id_grand_parent_join_object_entity.id3 = parentObj.parent_id"
    )
    assertContains(sql, "parentObj_parent_id_grand_parent_join_object_entity.id3 = #{id}")
    val criteria = q.query?.criterion?.first()
    assertNotNull(criteria)
    val fromDeclaration = q.query?.resolveFrom(false)
    assertNotNull(fromDeclaration)
    val joins = fromDeclaration.joins
    assertEquals(2, joins.size)
    val on = joins.last().joinCondition
    assertEquals(
        "parentObj_parent_id_grand_parent_join_object_entity.id3 = parentObj.parent_id",
        on.toSql(methodInfo)
    )
  }

}
